'''
Created on 2012-8-2

@author: DXD.Spirits
'''

from shortcuts import log_info
import math
import globalmap
import graph_connector


AVG_TRANSFER_TIME = 300 #seconds
USUAL_WALKING_DIS = 500 #m
MAX_WALKING_DIS = USUAL_WALKING_DIS * 3


def intra_graph_transfers(dataset_name, adjacency = None):
    ''' make transfer links for nearby stop
            the neighbourhood radius of a stop depends on his nearest next/previous stop
        If both bypassed stop A and bypassed stop B have the same next/previous stops, 
            we don't creat transfer link between A and B because we prefer to transfer in the next/previous stop 
    '''
    log_info("Intra graph transfers: " + dataset_name)
    
    if adjacency is None:
        adjacency = graph_connector.load_adjacency_matrix(dataset_name)
    
    log_info("Number of Stops: %d" % len(adjacency))
    
    coordinate = graph_connector.load_coordinates(dataset_name)
    transfer_arcs = set()
    for node in adjacency:
        lat, lon = coordinate[node]
        radius = USUAL_WALKING_DIS
        """ find a nearest next/previous stop """
        lat_min, lat_max, lon_min, lon_max = globalmap.circle2tile(lat, lon, radius)
        min_arc_len2 = USUAL_WALKING_DIS * USUAL_WALKING_DIS << 2
        for neighbour in adjacency[node]:
            nlat, nlon = coordinate[neighbour]
            if (lat_min < nlat < lat_max and lon_min < nlon < lon_max):
                dis2 = globalmap.distance_square(lat, lon, nlat, nlon)
                min_arc_len2 = min(min_arc_len2, dis2)
        min_arc_len = int(math.sqrt(min_arc_len2))
        radius = min(USUAL_WALKING_DIS, min_arc_len >> 1)
        """ If there is a next/previous stop nearer, we wont go farther """
        neighbour_list = globalmap.find_neighbours(lat, lon, radius, dataset_name)
        for neighbour in neighbour_list:
            if node != neighbour and node not in adjacency[neighbour] and neighbour not in adjacency[node]:
                transfer_arcs.add((node, neighbour))
                transfer_arcs.add((neighbour, node))
    
    log_info("%d transfer arcs found for %s" % (len(transfer_arcs), dataset_name))
    transfer_arcs = [(x, y, AVG_TRANSFER_TIME) for (x, y) in transfer_arcs]
    return transfer_arcs


def inter_graph_transfers(dataset1, dataset2):
    ''' make transfer links between 2 datasets
        the neighbourhood radius of a stop depends on his nearest next/previous stop
    '''
    log_info("inter graph transfers: %s, %s" % (dataset1, dataset2))
    
    adjacency1 = graph_connector.load_local_graph(dataset1)
    adjacency2 = graph_connector.load_local_graph(dataset2)
    
    node_coor = {}
    node_list1 = graph_connector.load_coordinates(dataset1)
    node_list2 = graph_connector.load_coordinates(dataset2)
    node_coor.update(node_list1)
    node_coor.update(node_list2)
    
    transfer_arcs = set()
    intersect = set()
    for _i in range(2):
        lat_min = min([coor[0] for coor in node_list2.values()])
        lat_max = max([coor[0] for coor in node_list2.values()])
        lon_min = min([coor[1] for coor in node_list2.values()])
        lon_max = max([coor[1] for coor in node_list2.values()])
        for node1 in adjacency1:
            latitude, longitude = node_coor[node1]
            if len(adjacency1[node1]) > 0:
                dis_list = [globalmap.distance_square(latitude, longitude, node_coor[nb][0], node_coor[nb][1]) 
                            for nb in adjacency1[node1]]
                min_next_stop_dis = int(math.sqrt(min(dis_list)))
                radius = min(USUAL_WALKING_DIS, min_next_stop_dis >> 1)
            else:
                radius = USUAL_WALKING_DIS
            delta_lat = radius * 10 / 11
            delta_lon = delta_lat * 81000000000000 / (81000000000000 - latitude * latitude)
            if (lat_min - delta_lat <= latitude <= lat_max + delta_lat and 
                lon_min - delta_lon <= longitude <= lon_max + delta_lon):
                neighbours = globalmap.find_neighbours(latitude, longitude, radius, dataset2)
                if len(neighbours) > 0:
                    intersect.add(node1)
                    for nb_dataset_id, nb_node_id in neighbours:
                        node2 = nb_dataset_id, nb_node_id
                        intersect.add(node2)
                        if node1 != node2:
                            transfer_arcs.add((node1, node2))
                            transfer_arcs.add((node2, node1))
        dataset1, dataset2 = dataset2, dataset1
        adjacency1, adjacency2 = adjacency2, adjacency1
        node_list1, node_list2 = node_list2, node_list1
    
    # TODO: Re-define the overlapping rate
    #intersection_percentage = float(len(intersect)) / float(len(adjacency1) + len(adjacency2))
    intersection_mesure = float(len(intersect)) / float(min(len(adjacency1), len(adjacency2)))
    overlapped = intersection_mesure >= 1
    log_info(" - %s, %s %d arcs found, overlapped? %s %.3f" % (dataset1, dataset2, len(transfer_arcs), overlapped, intersection_mesure))
    transfer_arcs = [(x, y, AVG_TRANSFER_TIME) for (x, y) in transfer_arcs]
    return transfer_arcs, overlapped



if __name__ == "__main__":
    log_info("go away")


